﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using TI_EntityLib;
using TiPort.TiEntityObjects;
using System.Collections;
using Helper;
using TI_EntityLib.TiEntityObjects.DayLog;
using TiEntityObject.Transport;


namespace TI
{
    public class DayLoader
    {
        public DateTime Day { get; set; }
        
        public DayLoader(DateTime day)
        {
            Day = day; 
        }
  
        public void Run()
        {
            Console.WriteLine("--------------------------------------" + Day.ToString () + "----------------------");
            //DayLogTransportSession session = new DayLogTransportSession() { Start = Helper.Time.GetDateInMSWithHour(Day), SessionType = DayLogTransportSessionType.DataProcessed};
            //DayLog.GetInstance(Day).Save();
            try
            {
                List<TransportFolder> folderLst = new List<TransportFolder>();

                //собираем данные из папок 
                string[] d = Directory.GetDirectories(TransportConfig.Instance.GetFtpDayFolder(this.Day));

                //формируем список папок
                Func<string, bool> addFL = delegate(string s) { 
                    folderLst.Add(new TransportFolder(s)); return true; 
                };
                d.All(addFL);

                //Идем по папкам формируем транспортный лист
                List<TransportFile> transportList = new List<TransportFile>();

                //Распаковываем все папки формируем список конвертации
                Func<TransportFolder, bool> unpackFolder = delegate(TransportFolder f)
                {
                    //если есть что то нераспакованное и необработааное добавляем в список
                    Console.WriteLine("Decompress" + f.FolderName);
                    UnZipFolder(f.FolderName);
                    transportList.AddRange(GetTransportFileList(f.FolderName));
                    return true;
                };
                folderLst.All(unpackFolder);

                ///Сохраняем транспортные файлы
                Save2DbTransportList(transportList);

                //При вставке на слабых машинках - нехватака памяти ошибки по TimeOut - попытаться прогнать еще раз

                TrySave2DbErrTransport();
            }
            finally
            {
                //session.End = Helper.Time.GetDateInMSWithHour(this.Day);
                //DayLog.GetInstance(this.Day).Transport.TransportSessions.Add(session);
                //DayLog.GetInstance(this.Day).Save();
            }
        }

        private void TrySave2DbErrTransport(){

           List<string> ErrFiles = new List<string>();
           List<TransportFile> transportFiles = new List<TransportFile>(); 

           string[] folders= Directory.GetDirectories (TransportConfig.Instance.GetFtpDayFolder(this.Day));
           foreach (string i in folders)
           {
               string[] fl = Directory.GetFiles(i, "*.ProcessedERR"); 
               ErrFiles .AddRange (fl);
           }

           string newName = string.Empty;
           foreach (string s in ErrFiles)
           {
               FileInfo fi = new FileInfo(s);
               newName = s.Replace(".ProcessedERR", ".xml");
               Helper.FileTools .RenameFile (s,newName);
               transportFiles.Add(new TransportFile(fi.Directory.FullName, newName)); 
           }

           Save2DbTransportList(transportFiles);    
            
        }

        private List<TransportFile> GetTransportFileList(string folder)
        {
            List<TransportFile> result = new List<TransportFile>();
            string[] files = System.IO.Directory.GetFiles(folder, "*.xml");
            foreach (string i in files)
            {
                result.Add (new TransportFile (folder ,i));
            }
            return result;
        }

        private void UnZipFolder(string folder)
        {
            string[] files = Directory.GetFiles(folder, "*.zip");
            foreach (string i in files)
            {
                try
                {
                    Helper.FileTools.Decompress(i);
                    Console.WriteLine(i + ":DecompressOK");
               }
                catch
                {
                    Helper.FileTools.RenameFile(i, i.Replace(".zip", ".DecompressERR"));
                    Console.WriteLine(i + ":DecompressErr");
                }
            }
            //чистим папку
            foreach (string i in files)
            {
                try
                {
                    File.Delete(i);
                }
                catch
                {
                    continue;
                }
            }
            
         }

        private void Save2DbTransportList(List<TransportFile> fileLst)
        {
           foreach (TransportFile f in fileLst)
            {
                    SaveToDb(f);
            }
        }
       
        public  void SaveToDb(TransportFile transportFile)
        {
            exportBase l = null;
            try
            {   
                //прогружаем XML
                transportFile.Load();
                
                // список объектов 
                l = transportFile.GetEntityList(this.Day);

                if (null == l)
                {
                    Helper.FileTools.RenameFile(transportFile.FileName, transportFile.FileName.Replace(".xml", ".EMPTY"));
                    transportFile.AddStatusList(new TransportFileStatus() { Date = DateTime.Now, Status = TransportFileStatusName.ProcessedOk });  
                    return;
                }

            }
            catch (Exception e) // ошибки серилизации
            {
                Helper.FileTools.RenameFile(transportFile.FileName, transportFile.FileName.Replace(".xml", ".ProcessedERR"));
                transportFile.FileName = transportFile.Name + ".xm_err";
                transportFile.AddStatusList(new TransportFileStatus() { Date = DateTime.Now, Status = TransportFileStatusName.ProcessedErr,Message =e.Message});
                return;            
            }

         
            string script = string.Empty;
            string currrentID = string.Empty;
            int entityCount = 0;
                         
            ICollection lst = l.GetCollection();
            DateTime sOperation = DateTime.Now;
            DateTime eOperation = DateTime.Now;
                foreach (IDbRootObject i in lst)
                {

                    ///ФИЛЬТР МЕДИЦИНА
                    if (i.Class != TI_EntityLib.TiEntityObjects.TiEntityClass.Pharm )
                    continue;

                    try
                    {
                        sOperation = DateTime.Now;
                        currrentID = i.Key;                   
                        script = i.GetInsertScript();
                        MongoTools.Instance.ExecuteScript(script);
                        
                        eOperation = DateTime.Now;
                        Console.WriteLine("{0},{1}, Time:{2}",transportFile.Name,i.Key,eOperation-sOperation );
                        ++entityCount;
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                        Helper.FileTools.RenameFile(transportFile.FileName, transportFile.FileName.Replace(".xml", ".ProcessedERR"));
                        SaveErrFile(script, transportFile.Name+currrentID);
                        System.Threading.Thread.Sleep(3000);
                        //log.CurrentFolder.AddErrFile(transportFile.FileName);
                        continue;
                    }
                }

                transportFile.EntityCount = entityCount; 
                Helper.FileTools.RenameFile(transportFile.FileName, transportFile.FileName.Replace(".xml", ".OK"));
                transportFile.FileName = transportFile.Name + ".OK";
                transportFile.AddStatusList(new TransportFileStatus() { Date = DateTime.Now, Status = TransportFileStatusName.ProcessedOk });
            }
     
        public  void SaveErrFile(string ErrScript, string FileName)
        {
            FileTools.СeckAndCreateFolder(TransportConfig.Instance.ErrXmlFolder);
            StreamWriter sr = File.CreateText(TransportConfig.Instance.ErrXmlFolder + FileName);
            sr.WriteLine(ErrScript);
            sr.Close();
        }
    }
}

